#include "correspondent.h"
#include "userconfig.h"
#include <string.h>

int correspondent_Run(uintptr_t wObjectAddr);
int correspondent_Clock(uintptr_t wObjectAddr);
static uint8_t s_chCorrespondentGetData[100];
GMSI_MSG_ITEM_DECLARE(CORRESPONDENT, CorrespondentFrameData, 100);

// gmsi
static gmsi_base_t s_tCorrespondentBase;
gmsi_base_cfg_t s_tCorrespondentBaseCfg = {
    .wId = CORRESPONDENT,
    .wParent = 0,
    .FcnInterface = {
        .Clock = correspondent_Clock,
        .Run = correspondent_Run,
    },
};

GMSI_MSG_ITEM_DECLARE(CORRESPONDENT, CaptureingData, 20);
gcoroutine_handle_t tGcoroutineCorrespondentHandle = {
    .bIsRunning = false,
    .pfcn = NULL,
};

/**
 * Function: correspondent_EventHandle
 * ----------------------------
 * This function handles events for the correspondent object.
 *
 * Parameters: 
 * ptThis: The address of the correspondent object.
 * wEvent: The event to handle.
 *
 * Returns: 
 * None
 */
void correspondent_EventHandle(correspondent_t *ptThis, uint32_t wEvent)
{
    if(wEvent & INCLUSIVE_Event_UpdatePosition)
    {
        //GLOG_PRINTF("correspondent_EventHandle INCLUSIVE_Event_Captureimg");
        uint8_t* pchData = GMSI_MSG_ITEM_GET_BUFFER(CorrespondentFrameData);
        pchData[FRAME_VALUE1] = 0x00;
        pchData[FRAME_VALUE2] = 0x01;
        pchData[FRAME_VALUE3] = 0x00;
        pchData[FRAME_VALUE4] = 0x01;
        pchData[FRAME_VALUE5] = 0x00;
        pchData[FRAME_VALUE6] = 0x01;
        ptThis->Write(ptThis->wFd, GMSI_MSG_ITEM_GET_BUFFER(CorrespondentFrameData), \
                    GMSI_MSG_ITEM_GET_LENGTH(CorrespondentFrameData));
    }
}

/**
 * Function: correspondent_Run
 * ----------------------------
 * This function runs the correspondent object. It handles events for the object, reads data from a file descriptor, 
 * checks the data's source and handles it accordingly. If the data length is not zero, it writes the data back to the file descriptor.
 *
 * Parameters: 
 * wObjectAddr: The address of the correspondent object.
 *
 * Returns: 
 * A status code indicating the result of the function. The possible return values depend on the 
 * implementation of the GMSI_SUCCESS constant.
 */
int correspondent_Run(uintptr_t wObjectAddr)
{
    int wRet = GMSI_SUCCESS;
    uint16_t hwLength = 0;
    uint16_t hwValue;
    
    // get ptr
    correspondent_t *ptThis = (correspondent_t *)wObjectAddr;
    
    // handle event
    uint32_t wEvent = gbase_EventPend(ptThis->ptBase);
    correspondent_EventHandle(ptThis, wEvent);
    uint8_t* pchData = GMSI_MSG_ITEM_GET_BUFFER(CorrespondentFrameData);
    // handle uart
    hwLength = ptThis->Read(ptThis->wFd, s_chCorrespondentGetData);
    if(hwLength)
    {
        GMSI_MSG_ITEM_UPDATE(CorrespondentFrameData, s_chCorrespondentGetData, hwLength);
        // echo test
        if(true == CHECK_HEAD_CORRESPONDENT(s_chCorrespondentGetData[FRAME_HEAD1], s_chCorrespondentGetData[FRAME_HEAD2]))
        {
            switch(s_chCorrespondentGetData[FRAME_FUNCTION])
            {
                // led控制
                case FUNCTION_V_LIGHT:
                case FUNCTION_N_LIGHT:   
                case FUNCTION_H_LIGHT:
                case FUNCTION_UVLIGHT:
                case FUNCTION_D_LIGHT:
                case FUNCTION_UVLIGHT405:
                    // send event to flashled
                    // gbase_EventPost(FLASHLED, INCLUSIVE_Event_Captureimg);
                    break;
            }
            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Captureimg);
        }
        else if(true == CHECK_HEAD_INCLUSIVE(s_chCorrespondentGetData[FRAME_HEAD1], s_chCorrespondentGetData[FRAME_HEAD2]))
        {
            if(s_chCorrespondentGetData[FRAME_ADDR] == 0x01)
            {
            
            }
            else if(s_chCorrespondentGetData[FRAME_ADDR] == 0x02)
            {
                switch(s_chCorrespondentGetData[FRAME_FUNCTION])
                {
                    // control the trigger by value1
                    case FUNCTION_HARD_TRIG:
                        hwValue = s_chCorrespondentGetData[FRAME_VALUE1];
                        //gbase_EventPost(CAPTUREIMG, hwValue&0x1F);
                        gbase_EventPost(CAPTUREIMG, 0x1F);
                        pchData[FRAME_VALUE1] = 0x11;
                        ptThis->Write(ptThis->wFd, GMSI_MSG_ITEM_GET_BUFFER(CorrespondentFrameData), \
                                        GMSI_MSG_ITEM_GET_LENGTH(CorrespondentFrameData));
                        break;
                    // control the dispenser by value1 、value2 、value3
                    case FUNCTION_DISPENSER:
                        // 0x01: start the scattered spots1
                        if(s_chCorrespondentGetData[FRAME_VALUE1])
                        {
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StartScatteredSpots1);
                            pchData[FRAME_VALUE1] = 0x11;
                        }
                        else
                        {
                            pchData[FRAME_VALUE1] = 0x01;
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StopScatteredSpots1);
                        }
                        // 0x02: start the scattered spots2
                        if(s_chCorrespondentGetData[FRAME_VALUE2])
                        {
                            pchData[FRAME_VALUE2] = 0x11;
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StartScatteredSpots2);
                        }
                        else
                        {
                            pchData[FRAME_VALUE2] = 0x01;
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StopScatteredSpots2);
                        }
                        // 0x03: start the scattered spots3
                        if(s_chCorrespondentGetData[FRAME_VALUE3])
                        {
                            pchData[FRAME_VALUE3] = 0x11;
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StartScatteredSpots3);
                        }
                        else
                        {
                            pchData[FRAME_VALUE3] = 0x01;
                            gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StopScatteredSpots3);
                        }
                        ptThis->Write(ptThis->wFd, GMSI_MSG_ITEM_GET_BUFFER(CorrespondentFrameData), \
                                        GMSI_MSG_ITEM_GET_LENGTH(CorrespondentFrameData));
                        break;
                    case FUNCTION_STEP_MOTOR:
                        GMSI_MSG_ITEM_UPDATE(CaptureingData, &s_chCorrespondentGetData[FRAME_VALUE1], 6);
                        gbase_MessagePost(CAPTUREIMG, GMSI_MSG_ITEM_GET_HANDLE(CaptureingData));
                        break;
                }
            }
        }
        else
        {
            if(hwLength == 1)
            {
                if(s_chCorrespondentGetData[0] == 0x11)
                {
                    gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StartScatteredSpotsAll);
                }
                else if(s_chCorrespondentGetData[0] == 0x22)
                {
                    gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_StopScatteredSpotsAll);
                }
                else if(s_chCorrespondentGetData[0] < 0x5)
                {
                    if(!s_chCorrespondentGetData[0])
                        gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Trigger1);
                    else if(s_chCorrespondentGetData[0] == 0x01)
                        gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Trigger2);
                    else if(s_chCorrespondentGetData[0] == 0x02)
                        gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Trigger3);
                    else if(s_chCorrespondentGetData[0] == 0x03)
                        gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Trigger4);
                    else if(s_chCorrespondentGetData[0] == 0x04)
                        gbase_EventPost(CAPTUREIMG, INCLUSIVE_Event_Trigger5);
                }
            }
            else
            {
                GMSI_MSG_ITEM_UPDATE(CaptureingData, s_chCorrespondentGetData, hwLength);
                gbase_MessagePost(CAPTUREIMG, GMSI_MSG_ITEM_GET_HANDLE(CaptureingData));
            }
        }
    }
    
    return wRet;
}

/**
 * Function: correspondent_Clock
 * ----------------------------
 * This function is the clock function for the correspondent object. It decrements the poll counter and tests for a timeout.
 *
 * Parameters: 
 * wObjectAddr: The address of the correspondent object.
 *
 * Returns: 
 * A status code indicating the result of the function. The possible return values depend on the 
 * implementation of the GMSI_SUCCESS constant.
 */
int correspondent_Clock(uintptr_t wObjectAddr)
{
    int wRet = GMSI_SUCCESS;
    static uint16_t s_hwTimeout = 0;
    correspondent_t *ptThis = (correspondent_t *)wObjectAddr;
    
    // poll counter
    if(ptThis->hwPollCount>1)
        ptThis->hwPollCount--;
    
    // test
    if(s_hwTimeout)s_hwTimeout--;
    
    if(!s_hwTimeout)
    {
        s_hwTimeout = 3000;
        //GLOG_PRINTF("correspondent timeout");
    }
    
    return wRet;
}

/**
 * Function: correspondent_Init
 * ----------------------------
 * This function initializes the correspondent object. It sets the object's base, parent, read and write functions.
 *
 * Parameters: 
 * wObjectAddr: The address of the correspondent object.
 * wObjectCfgAddr: The address of the correspondent configuration object.
 *
 * Returns: 
 * A status code indicating the result of the function. The possible return values depend on the 
 * implementation of the GMSI_SUCCESS constant.
 */
int correspondent_Init(uintptr_t wObjectAddr, uintptr_t wObjectCfgAddr)
{
    int wRet = GMSI_SUCCESS;

    correspondent_t *ptThis = (correspondent_t *)wObjectAddr;
    correspondent_cfg_t *ptCfg = (correspondent_cfg_t *)wObjectCfgAddr;
    
    ptThis->ptBase = &s_tCorrespondentBase;

    if(NULL == ptThis->ptBase)
        wRet = GMSI_EAGAIN;
    else
    {
        // set ptr to parent 
        s_tCorrespondentBaseCfg.wParent = wObjectAddr;
        wRet = gbase_Init(ptThis->ptBase, &s_tCorrespondentBaseCfg);
    }
    
    if(NULL != ptCfg->Read)
        ptThis->Read = ptCfg->Read;
    else
        wRet = GMSI_EAGAIN;
    
    if(NULL != ptCfg->Write)
        ptThis->Write = ptCfg->Write;
    else
        wRet = GMSI_EAGAIN;
    
    
    return wRet;
}



